package httphandler

import (
	"fmt"
	"net/http"
	"strconv"
	"time"

	"chat.com/common"
	"chat.com/library"
	"chat.com/model"
	"chat.com/pkg/logger"
	"chat.com/server/wsserver/connection"
	"chat.com/server/wsserver/service"
	"chat.com/setting"
	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

var upgrader websocket.Upgrader

var (
	accServerName string
	rpcServerName string
	accServerAddr string
	rpcServerAddr string
)

func Init() {
	upgrader = websocket.Upgrader{
		// 解决跨域问题
		CheckOrigin: func(r *http.Request) bool {
			return true
		},
	}

	accServerName = setting.AccServerSetting.Name
	rpcServerName = setting.RpcServerSetting.Name
	accServerAddr = setting.AccServerSetting.Host
	rpcServerAddr = setting.RpcServerSetting.Host
}

// 用户登录
func Login(c *gin.Context) {

	appId, _ := strconv.ParseInt(c.Query("app_id"), 10, 64)
	userId, _ := strconv.ParseInt(c.Query("user_id"), 10, 64)
	password := c.Query("password")

	// todo:进行用户权限认证，一般是客户端传入TOKEN，然后检验TOKEN是否合法，通过TOKEN解析出来用户ID
	// 这里只是演示
	if userId < 0 || userId >= 1000000 || password == "haha" {
		logger.Debug("用户登录 非法的用户", userId)
		Response(c, common.Unauthorized, "登陆失败 请重试", nil)
		return
	}

	if !library.InAppIds(appId) {
		logger.Debug("用户试图登录 不支持的平台", appId)
		Response(c, common.NotImplemented, "试图登录 不支持的平台", nil)
		return
	}

	// 登陆成功 返回token
	data := make(map[string]interface{})
	data["token"] = "123"

	Response(c, common.OK, "登陆成功", data)
	return
}

// 用于升级到websocket连接
func WsPage(c *gin.Context) {

	token := c.Query("token")
	appId, _ := strconv.ParseInt(c.Query("app_id"), 10, 64)
	userId, _ := strconv.ParseInt(c.Query("user_id"), 10, 64)

	loginInfo := common.WsLogin{
		Token:  token,
		AppId:  appId,
		UserId: userId,
	}

	// 模拟token验证失败
	if loginInfo.Token != "123" {
		Response(c, common.Unauthorized, "用户token无效", nil)
		return
	}

	// 升级协议
	wsConn, err := (&websocket.Upgrader{CheckOrigin: func(r *http.Request) bool {
		logger.Info("升级协议", "ua:", r.Header["User-Agent"], "referer:", r.Header["Referer"])
		return true
	}}).Upgrade(c.Writer, c.Request, nil)

	if err != nil {
		logger.Error("升级websocket失败: 客户端ip: %s, error: %s", wsConn.RemoteAddr().String(), err.Error())
		Response(c, common.ServerError, "升级websocket失败", nil)
		return
	}

	logger.Info("建立websocket连接: 客户端ip: %s", wsConn.RemoteAddr().String())

	// 包装管理用户的websocket连接
	currentTime := uint64(time.Now().Unix())
	client := connection.NewConnection(wsConn.RemoteAddr().String(), wsConn, currentTime, 1)
	client.Login(loginInfo.AppId, loginInfo.UserId, currentTime)

	// redis注册用户在线信息
	userOnline := model.NewUserOnline(
		accServerName, rpcServerName, accServerAddr, rpcServerAddr,
		loginInfo.AppId, loginInfo.UserId, client.Addr, currentTime,
	)

	err = library.SetUserOnlineInfo(client.GetKey(), userOnline)
	if err != nil {
		logger.Debug("用户登录, 注册登录信息到redis失败", err)
		wsConn.Close()
		Response(c, common.ServerError, "注册登录信息到redis失败", nil)
		return
	}

	// 发送离线消息
	go client.SendOfflineMsg()
	// 启动2个goroutine分别实时监听conn的read和write事件
	go client.Read()
	go client.Write()

	// 注册登录用户连接到连接管理器
	connection.ConnectionManagerInstance.LoginCh <- client

	logger.Debug("用户建立websocket连接成功", client.Addr, loginInfo.UserId)
	Response(c, common.OK, "建立websocket连接成功", nil)
	return
}

// 查看用户是否在线
func Online(c *gin.Context) {
	userIdStr := c.Query("userId")
	userId, _ := strconv.ParseInt(userIdStr, 10, 64)
	appIdStr := c.Query("appId")
	appId, _ := strconv.ParseInt(appIdStr, 10, 64)

	logger.Debug("http_request 查看用户是否在线", userId, appIdStr)
	online := service.IsUserOnline(appId, userId)
	data := make(map[string]interface{})
	data["userId"] = userId
	data["online"] = online

	Response(c, common.OK, "OK", data)
}

// 用户添加好友
func AddSingleFriend(c *gin.Context) {
	var req common.HttpAddSingleFriendRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		Response(c, common.ParameterIllegal, "BadRequest", nil)
	}

	fmt.Printf("http_request 添加好友: %d 添加 %d", req.SenderId, req.RecieverId)

	// 添加好友关系
	if ok := service.AddSingleFriend(req.SenderId, req.RecieverId); !ok {
		Response(c, common.ServerError, "添加好友失败", nil)
		return
	}

	Response(c, common.OK, "添加好友成功", nil)
}

// 用户加群
func JoinGroup(c *gin.Context) {
	var req common.HttpJoinGroupRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		Response(c, common.ParameterIllegal, "BadRequest", nil)
	}

	logger.Debug("http_request 用户加入群: %s 加入 %s", req.SenderId, req.GroupId)
	data := make(map[string]interface{})

	// 添加群成员
	if ok := service.JoinGroup(req.GroupId, req.SenderId); !ok {
		data["sendResultsErr"] = "加群失败"
	}

	Response(c, common.OK, "OK", data)
}

/*
// 给用户发送消息
func SendMessage(c *gin.Context) {
	msg := &common.WsSingleChatRequest{}
	// 获取参数
	appIdStr := c.PostForm("appId")
	msg.AppId, _ = strconv.ParseInt(appIdStr, 10, 64)
	senderIdStr := c.PostForm("senderId")
	msg.SenderId, _ = strconv.ParseInt(senderIdStr, 10, 64)
	recieverIdStr := c.PostForm("recieverId")
	msg.RecieverId, _ = strconv.ParseInt(recieverIdStr, 10, 64)
	//msgId := c.PostForm("msgId")
	msg.Content = c.PostForm("content")
	msg.Type = c.PostForm("msgType")
	sentTimeStr := c.PostForm("sentTime")
	msg.SentTime, _ = strconv.ParseInt(sentTimeStr, 10, 64)

	logger.Debug("http_request 给用户发送消息", appIdStr, senderIdStr, recieverIdStr, msg.Content)

	data := make(map[string]interface{})

	// 通过websocket发送数据给接收者
	sendResult, err := service.SendSingleChatMessage(msg)
	if err != nil {
		data["sendResultsErr"] = err.Error()
	}

	data["sendResult"] = sendResult
	Response(c, common.OK, "OK", data)
}

// 给全员发送消息（系统消息）
func SendMessageAll(c *gin.Context) {
	// 获取参数
	// 获取参数
	appIdStr := c.PostForm("appId")
	appId, _ := strconv.ParseInt(appIdStr, 10, 32)
	senderIdStr := c.PostForm("senderId")
	senderId, _ := strconv.ParseInt(senderIdStr, 10, 64)
	recieverIdStr := c.PostForm("recieverId")
	recieverId, _ := strconv.ParseInt(recieverIdStr, 10, 64)
	//msgId := c.PostForm("msgId")
	content := c.PostForm("content")
	msgType := c.PostForm("msgType")
	sentTimeStr := c.PostForm("sentTime")
	sentTime, _ := strconv.ParseInt(sentTimeStr, 10, 64)

	logger.Debug("http_request 给全体用户发送消息", appIdStr, senderId, recieverId, content)

	data := make(map[string]interface{})
	sendResults, err := wsController.SendUserMessageAll(
		"chat", appId, msgType, content, senderId, recieverId, sentTime)
	if err != nil {
		data["sendResultsErr"] = err.Error()

	}

	data["sendResults"] = sendResults
	Response(c, common.OK, "OK", data)
}*/
